﻿/*
Esta libreria requiere que se incluya la libreria Common.js
*/

var origDocumentMouseMove;
var origDocumentMouseUp;

var dragStarted = false;
var mouseOffset = null;
var dragSetect  = null;

var dragSets    = [];
var curTarget   = null;
var lastTarget  = null;
var dragHelper  = null;
var tempDiv     = null;
var rootParent  = null;
var dragTrash   = null;
var trashPathImages = "" ;

Number.prototype.NaN0 = function(){return isNaN(this)?0:this;}

// Create our helper object that will show the item while dragging
Common.addEventListener(window, "load", createDragHelper);


// ----------------------------------------------------------------------------------
// Public Functions
// ----------------------------------------------------------------------------------

// Esta funcion permite definir un grupo de containers que podran intercambiar items
function CreateDragSet(source) 
{
	var dragSet = dragSets.length;
	dragSets[dragSet] = [];

    SetDragContainer(source, "source", dragSet);
	    
	for(var i=1; i<arguments.length; i++){
		var container = arguments[i];
	    SetDragContainer(container, "target", dragSet);
	}
}

function SetDragContainer(container, type, dragSet)
{
	dragSets[dragSet].push(container);
	    
	container.setAttribute('dragType', type);

	for(var j=0; j<container.childNodes.length; j++){

		// Firefox puts in lots of #text nodes...skip these
		if(container.childNodes[j].nodeName!='#text'){
			container.childNodes[j].setAttribute('dragSet', dragSet);
			container.childNodes[j].setAttribute('dragType', type);
			
			// rollover
			container.childNodes[j].onmouseover = new Function("DragItem_RollOverIn(this)");
			container.childNodes[j].onmouseout  = new Function("DragItem_RollOverOut(this)");
			container.childNodes[j].onmousedown = DragItem_MouseDown;
		}
	}
}

function SetTrash(obj) 
{
    dragTrash = obj;
}

// ----------------------------------------------------------------------------------
// Event Handlers
// ----------------------------------------------------------------------------------

function DragDrop_MouseMove(ev)
{
    ev = ev || window.event;
    
    if(!dragStarted) {
	    var target = ev.target || ev.srcElement; // (Firefox || Explorer)	
	    var dragSet = target.getAttribute('dragSet');
	    
	    if(dragSet!=null) {
            startDrag(ev, target, dragSet);
            dragStarted = true;
        }
    }
	
	// If we get in here we are dragging something
	if(curTarget) {
		// Coordenadas del mouse
		var mousePos = Common.getMouseCoords(ev);
		
		// move our helper div to wherever the mouse is (adjusted by mouseOffset)
		dragHelper.style.top  = mousePos.y - mouseOffset.y;
		dragHelper.style.left = mousePos.x - mouseOffset.x;
        
		var xPos = mousePos.x - mouseOffset.x + (parseInt(curTarget.getAttribute('startWidth')) /2);
		var yPos = mousePos.y - mouseOffset.y + (parseInt(curTarget.getAttribute('startHeight'))/2);

		var dragSet = curTarget.getAttribute('dragSet');
		var activeCont = getActiveCont(dragSet, xPos, yPos);

		// Our target object is in one of our containers.  Check to see where our div belongs
		if(activeCont) {
			insertIntoCont(activeCont, xPos, yPos)
		} 
		else {
			// our drag item is not in a container, so hide it.
			if(curTarget.style.display!='none'){
				curTarget.style.display  = 'none';
			}
		}
	}

	// mouseMove target
	lastTarget  = target;

	// this helps prevent items on the page from being highlighted while dragging
	return false;
}

function DragDrop_MouseUp(ev)
{
	if(curTarget) {
		// if the drag item is invisible we throw it away
		if(curTarget.style.display == "none") {
		    if( (curTarget.parentNode) && (curTarget.parentNode.className=="dragContainer") )
		    {
		        curTarget.parentNode.removeChild(curTarget);
		    }

            if(dragTrash)
                moveToTrash();
            else
        		dragHelper.style.display = "none";
		    
		}
        else { 
    		// hide our helper object - it is no longer needed
    		dragHelper.style.display = "none";

        	// make sure the drag item is visible
		    curTarget.style.display = "";
    	    curTarget.style.visibility = "";
            curTarget.onmouseover = new Function("DragItem_RollOverIn(this)");
            curTarget.onmouseout =  new Function("DragItem_RollOverOut(this)");
			curTarget.onmousedown = DragItem_MouseDown;            
   		    curTarget.setAttribute("dragType", "target");

		    var origClass = curTarget.getAttribute("origClass");
		    if(origClass) curTarget.className = origClass;
		    
	        var afterMoveFunction = curTarget.getAttribute("afterMoveFunction");
	        if(afterMoveFunction) {
	            eval(afterMoveFunction + "(curTarget)");
	        }
		}
	}

	curTarget  = null;
    document.onmousemove = origDocumentMouseMove;
    document.onmouseup = origDocumentMouseUp;
}


// ----------------------------------------------------------------------------------
// Functions over the items
// ----------------------------------------------------------------------------------

function DragItem_MouseDown(ev) 
{
    var iMouseDown;
    
    // chequeo que sea el boton izquierdo
    if(ev) {
        iMouseDown = (ev.button == 0); // Firefox
    }
	else {
        iMouseDown = (window.event.button == 1); // IE
      	ev = window.event;
    }

    // Atacheo los event handler a los eventos de la pagina
    if(iMouseDown) {
        origDocumentMouseMove = document.onmousemove;
        origDocumentMouseUp = document.onmouseup;    
        document.onmousemove = DragDrop_MouseMove;
        document.onmouseup = DragDrop_MouseUp;
        
        dragStarted = false;
    }
    
	return false;
}

function DragItem_RollOverIn(target) 
{
	var oClass = target.getAttribute('overClass');
	
	if(oClass){
		target.setAttribute('origClass', target.className);
		target.className = oClass;
	}
}

function DragItem_RollOverOut(target) 
{
    var origClass = target.getAttribute('origClass');
    if(origClass) target.className = origClass;
}


// ----------------------------------------------------------------------------------
// Private Functions
// ----------------------------------------------------------------------------------

function startDrag(ev, target, dragSet) 
{
    // si se saca un item del source hago una copia
    var dragType = target.getAttribute("dragType");
    if(dragType=="source") {
        curTarget = target.cloneNode(true);
    }
    else {
        curTarget = target;
    }
        
    // offset
    mouseOffset = getMouseOffset(target, ev);
    
    // parent
    rootParent = curTarget.parentNode;
 
    // Remove anything that is in our dragHelper DIV so we can put a new item in it.
    for(var i=0; i<dragHelper.childNodes.length; i++) {
        dragHelper.removeChild(dragHelper.childNodes[i]);
    }

    // Make a copy of the current item and put it in our drag helper.
    dragHelper.appendChild(curTarget.cloneNode(true));
    dragHelper.style.display = "block";
    Common.bringToFront(dragHelper, true);
    
    // set the class on our helper DIV if necessary
    var dragClass = curTarget.getAttribute('dragClass');
    if(dragClass) {
	    dragHelper.firstChild.className = dragClass;
	    dragHelper.firstChild.setAttribute("dragFlag", true);
    }

    // disable dragging from our helper DIV (it's already being dragged)
    dragHelper.firstChild.removeAttribute('dragSet');

    // Record the mouse x and y offset for the element
    recordPositions(dragSet, target);
    
    // hago invisible al item
    curTarget.style.visibility = "hidden";
}

function recordPositions(dragSet, realTarget) 
{
    // record the width/height of our drag item.  Then hide it.
    curTarget.setAttribute('startWidth',  parseInt(realTarget.offsetWidth));
    curTarget.setAttribute('startHeight', parseInt(realTarget.offsetHeight));
    curTarget.style.display  = 'none';

    // Record the current position of all drag/drop targets related to the element.
    var dragConts = dragSets[dragSet];

    for(var i=0; i<dragConts.length; i++){
	    with(dragConts[i]){
		    var pos = Common.getPosition(dragConts[i]);

		    setAttribute('startWidth',  parseInt(offsetWidth));
		    setAttribute('startHeight', parseInt(offsetHeight));
		    setAttribute('startLeft',   pos.x);
		    setAttribute('startTop',    pos.y);
	    }

	    // loop through each child element of each container
	    for(var j=0; j<dragConts[i].childNodes.length; j++){
		    with(dragConts[i].childNodes[j]){
			    if((nodeName=='#text') || (dragConts[i].childNodes[j]==curTarget)) continue;

			    var pos = Common.getPosition(dragConts[i].childNodes[j]);

			    setAttribute('startWidth',  parseInt(offsetWidth));
			    setAttribute('startHeight', parseInt(offsetHeight));
			    setAttribute('startLeft',   pos.x);
			    setAttribute('startTop',    pos.y);
		    }
	    }
    }
}

// check each drop container to see if our target object is "inside" the container
function getActiveCont(dragSet, xPos, yPos) 
{
    var dragConts = dragSets[dragSet];
    var activeCont = null;
    
    for(var i=1; i<dragConts.length; i++){
		with(dragConts[i]){
			if(((getAttribute('startLeft')) < xPos) &&
				((getAttribute('startTop')) < yPos) &&
				((parseInt(getAttribute('startLeft')) + parseInt(getAttribute('startWidth'))) > xPos) &&
				((parseInt(getAttribute('startTop')) + parseInt(getAttribute('startHeight'))) > yPos)){

                var type = curTarget.getAttribute("dragType");         

                if( (type == "source") || ((type=="target") && (rootParent==dragConts[i])) ) {
			        activeCont = dragConts[i];
			        break;
			    }
			}
		}
	}
	
	return activeCont;
}

function insertIntoCont(activeCont, xPos, yPos)
{
    // beforeNode will hold the first node AFTER where our div belongs
	var beforeNode = null;

	// loop through each child node (skipping text nodes).
	for(var i=activeCont.childNodes.length-1; i>=0; i--){
		with(activeCont.childNodes[i]){
			if(nodeName=='#text') continue;

			// if the current item is "After" the item being dragged
			if(
				curTarget != activeCont.childNodes[i] &&
				((parseInt(getAttribute('startLeft')) + parseInt(getAttribute('startWidth')))  > xPos) &&
				((parseInt(getAttribute('startTop'))  + parseInt(getAttribute('startHeight'))) > yPos)){
					beforeNode = activeCont.childNodes[i];
			}
		}
	}

	// the item being dragged belongs before another item
	if(beforeNode) {
		if(beforeNode!=curTarget.nextSibling){
			activeCont.insertBefore(curTarget, beforeNode);
		}

	// the item being dragged belongs at the end of the current container
	} else {
		if((curTarget.nextSibling) || (curTarget.parentNode!=activeCont)){
			activeCont.appendChild(curTarget);
		}
	}

	// make our drag item visible
	if(curTarget.style.display!=''){
		curTarget.style.display  = '';
	}
}

function getMouseOffset(target, ev)
{
	ev = ev || window.event;

	var docPos    = Common.getPosition(target);
	var mousePos  = Common.getMouseCoords(ev);

	return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}

function createDragHelper() 
{
	dragHelper = document.createElement('DIV');
    Common.setStyleAttribute(dragHelper, "position", "absolute");	
    Common.setStyleAttribute(dragHelper, "display", "none");	

	document.body.appendChild(dragHelper);
}

function moveToTrash()
{
    var trashPosition = Common.getPosition(dragTrash);
    moveTo(dragHelper, trashPosition);
}

function moveToTrashEnd()
{
    dragTrash.children[0].src = trashPathImages + "/trash_full.gif";
}


var moveContext;
var tMove;
var speed = 15;

function moveTo(obj, target)
{
    var source = Common.getPosition(obj);
    var pendiente = (target.y - source.y) / (target.x - source.x);
    var delta;
    
    if(target.x > source.x)
        delta = Math.max(speed, (target.x - source.x) / speed);
    else
        delta = Math.min(-speed, (target.x - source.x) / speed);
        
    moveContext =
    {
        d: delta,
        xpos : source.x,
        xend : target.x,
        p : pendiente,
        b : source.y - (pendiente * source.x),
        element : obj
    }

    window.clearInterval(tMove);
    tMove = window.setInterval(function () { moveToAux() }, 10);
}

function moveToAux() {
    
    moveContext.xpos += moveContext.d;
    
    if( Math.abs(moveContext.xpos - moveContext.xend) <= Math.abs(moveContext.d)) {
        window.clearInterval(tMove);
        moveContext.element.style.display = "none";
        moveToTrashEnd();
    }
    else {
		moveContext.element.style.left = moveContext.xpos;
		moveContext.element.style.top  = (moveContext.p * moveContext.xpos) + moveContext.b;
    }
}